#include<iostream>
#include<thread>
#include<future>
#include<memory>
//packaged_task 的使用
//  packaged_task 是个模板类， 实例化的对象可以对一个函数进行二次封装
// packaged_task 可以通过getfuture 获取一个future对象， 来获取封装的这个函数的异步结果

int Add(int num1, int num2)
{
    std::cout << "add 111" << std::endl;
    std::this_thread::sleep_for(std::chrono::seconds(5));

    std::cout << "add 222" << std::endl;
    return num1 + num2;
}


int main()
{
    // std::packaged_task<int(int, int)> task(Add);
    // std::future<int> fu = task.get_future();    //绑定

    //会报错 task本身可以当作函数执行 eg：task(11, 22) 但是类型和函数不一样 
    //不能当作async的异步执行任务  虽然没报错 编译会出问题
    //std::async(std::launch::async, task, 11, 22);     error
    //std::thread thr(task, 11, 22)     error
    //可以把task定义成为一个指针， 传递到线程中 然后进行解引用执行
    //但是如果单纯指针指向一个对象 存在生命周期问题 很可能出现风险
    //在堆上new对象 用智能指针管理生命周期

    //std::shared_ptr<std::packaged_task<int(int, int)> >ptask = std::make_shared<std::packaged_task<int(int, int)> >(Add);
    std::cout << "1 -------------------------" << std::endl;
    auto ptask = std::make_shared<std::packaged_task<int(int, int)> >(Add);
    std::future<int> fu = ptask->get_future();
    std::thread thr([ptask](){(*ptask)(11, 22);});

    std::cout << "2 -------------------------" << std::endl;
    int sum = fu.get(); 
    std::cout << "3 -------------------------" << std::endl;
    std::cout << sum << std::endl;

    thr.join();
    return 0;   
}